package com.example.mqtt.config;

import com.alibaba.fastjson2.JSON;
import com.example.mqtt.model.Card;
import com.example.mqtt.model.WebSocketMessage;
import jakarta.websocket.OnClose;
import jakarta.websocket.OnMessage;
import jakarta.websocket.OnOpen;
import jakarta.websocket.Session;
import jakarta.websocket.server.ServerEndpoint;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

@Component
@ServerEndpoint("/ws")
public class WebSocketEndpoint {

    private static final CopyOnWriteArrayList<Session> sessions = new CopyOnWriteArrayList<>();

    @OnOpen
    public void onOpen(Session session) {
        sessions.add(session);
        startHeartbeat(session);
        System.out.println("WebSocket connected: " + session.getId());
    }

    @OnClose
    public void onClose(Session session) {
        sessions.remove(session);
        System.out.println("WebSocket disconnected: " + session.getId());
    }

    @OnMessage
    public void onMessage(String message, Session session) {
        try {
            WebSocketMessage webSocketMessage = JSON.parseObject(message, WebSocketMessage.class);
            handleWebSocketMessage(webSocketMessage);
        } catch (Exception e) {
            System.err.println("Error parsing message: " + e.getMessage());
        }
    }

    private void handleWebSocketMessage(WebSocketMessage message) {
        if ("add_card".equals(message.getType())) {
            Card card = message.getCard();
            System.out.println("Received add_card: " + card.getName());
            broadcastAddCard(card);
        } else if ("remove_top_card".equals(message.getType())) {
            System.out.println("Received remove_top_card");
            broadcastRemoveTopCard();
        }
    }

    private void broadcastAddCard(Card card) {
        String message = JSON.toJSONString(new WebSocketMessage("add_card", card));
        broadcast(message);
    }

    private void broadcastRemoveTopCard() {
        String message = JSON.toJSONString(new WebSocketMessage("remove_top_card", null));
        broadcast(message);
    }

    public static void broadcast(String message) {
        sessions.forEach(session -> {
            try {
                if (session.isOpen()) {
                    session.getBasicRemote().sendText(message);
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        });
    }

    private void startHeartbeat(Session session) {
        ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor();
        scheduler.scheduleAtFixedRate(() -> {
            try {
                if (session.isOpen()) {
                    session.getBasicRemote().sendText("ping");
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }, 0, 30, TimeUnit.SECONDS);
    }
}